#ifndef QLIBSSH_GLOBAL_H
#define QLIBSSH_GLOBAL_H

#include <QtCore/qglobal.h>
#include <string>
#include <QDebug>

#if defined(QLIBSSH_LIBRARY)
#define QLIBSSH_EXPORT Q_DECL_EXPORT
#else
#define QLIBSSH_EXPORT Q_DECL_IMPORT
#endif

struct QLIBSSH_EXPORT SshLoginKeys {
    std::string user;
    std::string host;
    int port;
    std::string password;
};

template<class T>
class QLIBSSH_EXPORT SharePtr {
public:
    explicit SharePtr(const T& p) {
        if (p != nullptr) {
            mPtr = p;
            mRefCount = new std::atomic<int>(1);
        }
    }
    // 自定义ptr析构函数
    virtual ~SharePtr()=default;

    SharePtr(const SharePtr<T>& p) : mPtr(p.mPtr), mRefCount(p.mRefCount) {
        if (mPtr !=nullptr) {
            mRefCount->fetch_add(1, std::memory_order_relaxed);
        }
    }

    SharePtr(SharePtr<T>&& p)  noexcept :  mPtr(p.mPtr), mRefCount(p.mRefCount) {
        if (p.mPtr != nullptr) {
            p.mPtr = nullptr;
            p.mRefCount = nullptr;
        }
    }

    SharePtr<T>& operator=(const SharePtr<T>& p) {
        if (this == &p) {
            return *this;
        }

        if (p.mPtr == nullptr) {
            return *this;
        }

        this->mPtr = p.mPtr;
        this->mRefCount = p.mRefCount;
        this->mRefCount->fetch_add(1, std::memory_order_relaxed);
        return *this;
    }

    SharePtr<T>& operator=(SharePtr<T>&& p) noexcept {
        if (this == &p || p.mPtr == nullptr) {
            return *this;
        }

        this->mPtr = p.mPtr;
        this->mRefCount = p.mRefCount;
        p.mPtr = nullptr;
        p.mRefCount = nullptr;

        return *this;
    }

    T operator->() const {
        return mPtr;
    }

    [[nodiscard]] T Get() const {
        return mPtr;
    }

    bool IsNull() {
        return mPtr == nullptr;
    }

    [[nodiscard]] unsigned int GetRefCount() const {
        return mPtr ? mRefCount->load(std::memory_order_relaxed) : 0;
    }

    void Swap(SharePtr<T>& p) {
        std::swap(mPtr, p.mPtr);
        std::swap(mRefCount, p.mRefCount);
        p.mPtr = nullptr;
        p.mRefCount = nullptr;
    }

protected:
    T mPtr {nullptr};
    std::atomic<int>* mRefCount {nullptr};
};

#endif // QLIBSSH_GLOBAL_H
